﻿#region Copyright (c) Nicola Gallo All rights reserved.
/*
 * All rights reserved. Reproduction of trasmission of this file, or a portion thereof,
 * is forbidden without prior written permission of Nicola Gallo.
 * 
 * Author: Nicola Gallo
 * Date: 09/04/2011
 * 
 * */
#endregion
namespace PrismMVC.Shell.Containers
{
    //.NET References.
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;

    //Microsoft References
    using Microsoft.Practices.Prism.Modularity;
    using Microsoft.Practices.Prism.Logging;
    using Microsoft.Practices.Prism.Events;
    using Microsoft.Practices.Unity;

    //PrismMVC References
    using PrismMVC.Shell.Data;
    using PrismMVC.Shell.MVC;

    /// <summary>
    /// Defines a presentation model class.
    /// </summary>
    public class PresentationModel : IPresentationModel, ISupportViewData
    {
        //Events

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        //Fields

        private ViewDataDictionary _viewData;

        //Constructors

        /// <summary>
        /// Creates a new instance of <see cref="PresentationModel"/>.
        /// </summary>
        /// <param name="unityContainer">Unity container.</param>
        /// <param name="loggerFacade">Logger facade.</param>
        /// <param name="eventAggregator">Event aggregator.</param>
        public PresentationModel(IUnityContainer unityContainer, ILoggerFacade loggerFacade, IEventAggregator eventAggregator)
        {
            if (unityContainer == null)
            {
                throw new ArgumentNullException("UnityContainer parameter can not be equals to null.");
            }
            else if (loggerFacade == null)
            {
                throw new ArgumentNullException("LoggerFacade parameter can not be equals to null.");
            }
            else if (eventAggregator == null)
            {
                throw new ArgumentNullException("EventAggregator parameter can not be equals to null.");
            }
            this.UnityContainer = unityContainer;
            this.LoggerFacade = loggerFacade;
            this.EventAggregator = eventAggregator;
        }

        //Properties

        /// <summary>
        /// Gets/Sets the controller.
        /// </summary>
        internal IController Controller { get; set; }

        /// <summary>
        /// Gets <see cref="ViewData"/> identifier.
        /// </summary>
        public string ViewDataID { get; private set; }

        /// <summary>
        /// Gets the ViewDataDictionary.
        /// </summary>
        public ViewDataDictionary ViewData
        {
            get
            {
                if (this._viewData == null)
                {
                    this._viewData = ViewDataDictionaryFactory.CreateViewDataDictionary(this.ViewDataID);
                }
                return this._viewData;
            }
        }

        /// <summary>
        /// Gets the shell proxy.
        /// </summary>
        protected IUnityContainer UnityContainer { get; set; }

        /// <summary>
        /// Gets the logger facade.
        /// </summary>
        protected ILoggerFacade LoggerFacade { get; private set; }

        /// <summary>
        /// Gets the event aggregator.
        /// </summary>
        protected IEventAggregator EventAggregator { get; private set; }
    
        //Methods

        /// <summary>
        /// Sets the ViewDataDictionary identifier.
        /// </summary>
        /// <param name="ViewDataID">ViewDataDictionary identifier.</param>
        internal void SetsViewDataID(String ViewDataID)
        {
            if (string.IsNullOrWhiteSpace(ViewDataID))
            {
                throw new ArgumentException("ViewDataID paramater can not be equals to either null or empty string.");
            }
            this.ViewDataID = ViewDataID;
        }

        /// <summary>
        /// Raises the <see cref="PresentationModel.PropertyChanged"/> event for the input property name.
        /// </summary>
        /// <param name="propertyName"></param>
        protected void OnPropertyChanged(String propertyName) 
        {
            if (!string.IsNullOrWhiteSpace(propertyName))
            {
                PropertyChangedEventHandler propertyChangedHnd = this.PropertyChanged as PropertyChangedEventHandler;
                if (propertyChangedHnd != null)
                {
                    propertyChangedHnd(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

        /// <summary>
        /// Invokes an action.
        /// </summary>
        /// <param name="actionName">Action name.</param>
        /// <param name="args">Arguments.</param>
        public void InvokeAction(String actionName, object args)
        {
            if (!String.IsNullOrWhiteSpace(actionName))
            {
                this.Controller.InvokeAction(actionName, args);
            }
        }

        /// <summary>
        /// Called when presentation model is initialized.
        /// </summary>
        protected internal virtual void Initialize() { }
    }
}